Enter the directory of the maca folder on your drive and the name of the tissue you want to analyze.

tissue_of_interest = "Thymus"

Load the requisite packages and some additional helper functions.

library(here)
here() starts at /Users/olgabot/code/tabula-muris
library(useful)
Loading required package: ggplot2
library(Seurat)
Loading required package: cowplot

Attaching package: 'cowplot'
The following object is masked from 'package:ggplot2':

    ggsave
Loading required package: Matrix
Warning: namespace 'Biobase' is not available and has been replaced
by .GlobalEnv when processing object 'call.'
Warning: namespace 'lme4' is not available and has been replaced
by .GlobalEnv when processing object 'call.'
Warning: namespace 'MatrixModels' is not available and has been replaced
by .GlobalEnv when processing object 'call.'
Warning: namespace 'Biobase' is not available and has been replaced
by .GlobalEnv when processing object 'call.'
Warning: namespace 'lme4' is not available and has been replaced
by .GlobalEnv when processing object 'call.'
Warning: namespace 'MatrixModels' is not available and has been replaced
by .GlobalEnv when processing object 'call.'
library(dplyr)
Warning: package 'dplyr' was built under R version 3.4.2

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(Matrix)

save_dir = here('00_data_ingest', 'tissue_robj')
# read the metadata to get the plates we want
plate_metadata_filename = here('00_data_ingest', 'facs_raw_data', 'metadata_FACS.csv')

plate_metadata <- read.csv(plate_metadata_filename, sep=",", header = TRUE)
colnames(plate_metadata)[1] <- "plate.barcode"
plate_metadata

Subset the metadata on the tissue.

tissue_plates = filter(plate_metadata, tissue == tissue_of_interest)[,c('plate.barcode','tissue','subtissue','mouse.sex')]
tissue_plates

Load the read count data.

#Load the gene names and set the metadata columns by opening the first file
filename = here('00_data_ingest', 'facs_raw_data', 'FACS', paste0(tissue_of_interest, '-counts.csv'))

raw.data = read.csv(filename, sep=",", row.names=1)
# raw.data = data.frame(row.names = rownames(raw.data))
corner(raw.data)

Make a vector of plate barcodes for each cell

plate.barcodes = lapply(colnames(raw.data), function(x) strsplit(strsplit(x, "_")[[1]][1], '.', fixed=TRUE)[[1]][2])
head(plate.barcodes)
[[1]]
[1] "MAA000607"

[[2]]
[1] "MAA000607"

[[3]]
[1] "MAA000607"

[[4]]
[1] "MAA000607"

[[5]]
[1] "MAA000607"

[[6]]
[1] "MAA000607"
MAA000607
MAA000607
MAA000607
MAA000607
MAA000607
MAA000607

Use only the metadata rows corresponding to Bladder plates. Make a plate barcode dataframe to “expand” the per-plate metadata to be per-cell.

barcode.df = t.data.frame(as.data.frame(plate.barcodes))

rownames(barcode.df) = colnames(raw.data)
colnames(barcode.df) = c('plate.barcode')
head(barcode.df)
                        plate.barcode
H6.MAA000607.3_9_M.1.1  "MAA000607"  
I8.MAA000607.3_9_M.1.1  "MAA000607"  
J10.MAA000607.3_9_M.1.1 "MAA000607"  
K12.MAA000607.3_9_M.1.1 "MAA000607"  
A17.MAA000607.3_9_M.1.1 "MAA000607"  
A16.MAA000607.3_9_M.1.1 "MAA000607"  
MAA000607

MAA000607

MAA000607

MAA000607

MAA000607

MAA000607
rnames = row.names(barcode.df)
meta.data <- merge(barcode.df, plate_metadata, by='plate.barcode', sort = F)
row.names(meta.data) <- rnames

# Sort cells by plate barcode because that's how the data was originally
meta.data = meta.data[order(meta.data$plate.barcode), ]
corner(meta.data)
raw.data = raw.data[, rownames(meta.data)]
corner(raw.data)

Process the raw data and load it into the Seurat object.

# Find ERCC's, compute the percent ERCC, and drop them from the raw data.
erccs <- grep(pattern = "^ERCC-", x = rownames(x = raw.data), value = TRUE)
percent.ercc <- Matrix::colSums(raw.data[erccs, ])/Matrix::colSums(raw.data)
ercc.index <- grep(pattern = "^ERCC-", x = rownames(x = raw.data), value = FALSE)
raw.data <- raw.data[-ercc.index,]

# Create the Seurat object with all the data
tiss <- CreateSeuratObject(raw.data = raw.data, project = tissue_of_interest, 
                    min.cells = 5, min.genes = 5)

tiss <- AddMetaData(object = tiss, meta.data)
tiss <- AddMetaData(object = tiss, percent.ercc, col.name = "percent.ercc")
# Change default name for sums of counts from nUMI to nReads
colnames(tiss@meta.data)[colnames(tiss@meta.data) == 'nUMI'] <- 'nReads'

# Create metadata columns for annotations and subannotations
tiss@meta.data[,'annotation'] <- NA
tiss@meta.data[,'subannotation'] <- NA

Calculate percent ribosomal genes.

ribo.genes <- grep(pattern = "^Rp[sl][[:digit:]]", x = rownames(x = tiss@data), value = TRUE)
percent.ribo <- Matrix::colSums(tiss@raw.data[ribo.genes, ])/Matrix::colSums(tiss@raw.data)
tiss <- AddMetaData(object = tiss, metadata = percent.ribo, col.name = "percent.ribo")

A sanity check: genes per cell vs reads per cell.

GenePlot(object = tiss, gene1 = "nReads", gene2 = "nGene", use.raw=T)

Filter out cells with few reads and few genes.

tiss <- FilterCells(object = tiss, subset.names = c("nGene", "nReads"), 
    low.thresholds = c(500, 50000), high.thresholds = c(25000, 2000000))

Normalize the data, then regress out correlation with total reads

tiss <- NormalizeData(object = tiss)
tiss <- ScaleData(object = tiss, vars.to.regress = c("nReads", "percent.ribo","Rn45s"))
[1] "Regressing out nReads"       "Regressing out percent.ribo"
[3] "Regressing out Rn45s"       

  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |                                                                 |   1%
  |                                                                       
  |=                                                                |   1%
  |                                                                       
  |=                                                                |   2%
  |                                                                       
  |==                                                               |   3%
  |                                                                       
  |===                                                              |   4%
  |                                                                       
  |===                                                              |   5%
  |                                                                       
  |====                                                             |   5%
  |                                                                       
  |====                                                             |   6%
  |                                                                       
  |====                                                             |   7%
  |                                                                       
  |=====                                                            |   7%
  |                                                                       
  |=====                                                            |   8%
  |                                                                       
  |======                                                           |   9%
  |                                                                       
  |======                                                           |  10%
  |                                                                       
  |=======                                                          |  10%
  |                                                                       
  |=======                                                          |  11%
  |                                                                       
  |========                                                         |  12%
  |                                                                       
  |========                                                         |  13%
  |                                                                       
  |=========                                                        |  14%
  |                                                                       
  |==========                                                       |  15%
  |                                                                       
  |==========                                                       |  16%
  |                                                                       
  |===========                                                      |  16%
  |                                                                       
  |===========                                                      |  17%
  |                                                                       
  |===========                                                      |  18%
  |                                                                       
  |============                                                     |  18%
  |                                                                       
  |============                                                     |  19%
  |                                                                       
  |=============                                                    |  20%
  |                                                                       
  |==============                                                   |  21%
  |                                                                       
  |==============                                                   |  22%
  |                                                                       
  |===============                                                  |  22%
  |                                                                       
  |===============                                                  |  23%
  |                                                                       
  |===============                                                  |  24%
  |                                                                       
  |================                                                 |  24%
  |                                                                       
  |================                                                 |  25%
  |                                                                       
  |=================                                                |  26%
  |                                                                       
  |=================                                                |  27%
  |                                                                       
  |==================                                               |  27%
  |                                                                       
  |==================                                               |  28%
  |                                                                       
  |===================                                              |  29%
  |                                                                       
  |===================                                              |  30%
  |                                                                       
  |====================                                             |  31%
  |                                                                       
  |=====================                                            |  32%
  |                                                                       
  |=====================                                            |  33%
  |                                                                       
  |======================                                           |  33%
  |                                                                       
  |======================                                           |  34%
  |                                                                       
  |=======================                                          |  35%
  |                                                                       
  |=======================                                          |  36%
  |                                                                       
  |========================                                         |  37%
  |                                                                       
  |=========================                                        |  38%
  |                                                                       
  |=========================                                        |  39%
  |                                                                       
  |==========================                                       |  39%
  |                                                                       
  |==========================                                       |  40%
  |                                                                       
  |===========================                                      |  41%
  |                                                                       
  |===========================                                      |  42%
  |                                                                       
  |============================                                     |  43%
  |                                                                       
  |============================                                     |  44%
  |                                                                       
  |=============================                                    |  44%
  |                                                                       
  |=============================                                    |  45%
  |                                                                       
  |==============================                                   |  46%
  |                                                                       
  |===============================                                  |  47%
  |                                                                       
  |===============================                                  |  48%
  |                                                                       
  |================================                                 |  49%
  |                                                                       
  |================================                                 |  50%
  |                                                                       
  |=================================                                |  50%
  |                                                                       
  |=================================                                |  51%
  |                                                                       
  |==================================                               |  52%
  |                                                                       
  |==================================                               |  53%
  |                                                                       
  |===================================                              |  54%
  |                                                                       
  |====================================                             |  55%
  |                                                                       
  |====================================                             |  56%
  |                                                                       
  |=====================================                            |  56%
  |                                                                       
  |=====================================                            |  57%
  |                                                                       
  |======================================                           |  58%
  |                                                                       
  |======================================                           |  59%
  |                                                                       
  |=======================================                          |  60%
  |                                                                       
  |=======================================                          |  61%
  |                                                                       
  |========================================                         |  61%
  |                                                                       
  |========================================                         |  62%
  |                                                                       
  |=========================================                        |  63%
  |                                                                       
  |==========================================                       |  64%
  |                                                                       
  |==========================================                       |  65%
  |                                                                       
  |===========================================                      |  66%
  |                                                                       
  |===========================================                      |  67%
  |                                                                       
  |============================================                     |  67%
  |                                                                       
  |============================================                     |  68%
  |                                                                       
  |=============================================                    |  69%
  |                                                                       
  |==============================================                   |  70%
  |                                                                       
  |==============================================                   |  71%
  |                                                                       
  |===============================================                  |  72%
  |                                                                       
  |===============================================                  |  73%
  |                                                                       
  |================================================                 |  73%
  |                                                                       
  |================================================                 |  74%
  |                                                                       
  |=================================================                |  75%
  |                                                                       
  |=================================================                |  76%
  |                                                                       
  |==================================================               |  76%
  |                                                                       
  |==================================================               |  77%
  |                                                                       
  |==================================================               |  78%
  |                                                                       
  |===================================================              |  78%
  |                                                                       
  |===================================================              |  79%
  |                                                                       
  |====================================================             |  80%
  |                                                                       
  |=====================================================            |  81%
  |                                                                       
  |=====================================================            |  82%
  |                                                                       
  |======================================================           |  82%
  |                                                                       
  |======================================================           |  83%
  |                                                                       
  |======================================================           |  84%
  |                                                                       
  |=======================================================          |  84%
  |                                                                       
  |=======================================================          |  85%
  |                                                                       
  |========================================================         |  86%
  |                                                                       
  |=========================================================        |  87%
  |                                                                       
  |=========================================================        |  88%
  |                                                                       
  |==========================================================       |  89%
  |                                                                       
  |==========================================================       |  90%
  |                                                                       
  |===========================================================      |  90%
  |                                                                       
  |===========================================================      |  91%
  |                                                                       
  |============================================================     |  92%
  |                                                                       
  |============================================================     |  93%
  |                                                                       
  |=============================================================    |  93%
  |                                                                       
  |=============================================================    |  94%
  |                                                                       
  |=============================================================    |  95%
  |                                                                       
  |==============================================================   |  95%
  |                                                                       
  |==============================================================   |  96%
  |                                                                       
  |===============================================================  |  97%
  |                                                                       
  |================================================================ |  98%
  |                                                                       
  |================================================================ |  99%
  |                                                                       
  |=================================================================|  99%
  |                                                                       
  |=================================================================| 100%
[1] "Scaling data matrix"

  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=================================================================| 100%
tiss <- FindVariableGenes(object = tiss, do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.5)

Run Principal Component Analysis.

tiss <- RunPCA(object = tiss, do.print = FALSE)
tiss <- ProjectPCA(object = tiss, do.print = FALSE)

Later on (in FindClusters and TSNE) you will pick a number of principal components to use. This has the effect of keeping the major directions of variation in the data and, ideally, supressing noise. There is no correct answer to the number to use, but a decent rule of thumb is to go until the plot plateaus.

PCElbowPlot(object = tiss)

Choose the number of principal components to use.

# Set number of principal components. 
n.pcs = 10

The clustering is performed based on a nearest neighbors graph. Cells that have similar expression will be joined together. The Louvain algorithm looks for groups of cells with high modularity–more connections within the group than between groups. The resolution parameter determines the scale…higher resolution will give more clusters, lower resolution will give fewer.

For the top-level clustering, aim to under-cluster instead of over-cluster. It will be easy to subset groups and further analyze them below.

# Set resolution 
res.used <- 0.5

tiss <- FindClusters(object = tiss, reduction.type = "pca", dims.use = 1:n.pcs, 
    resolution = res.used, print.output = 0, save.SNN = TRUE)

To visualize

# If cells are too spread out, you can raise the perplexity. If you have few cells, try a lower perplexity (but never less than 10).
tiss <- RunTSNE(object = tiss, dims.use = 1:n.pcs, seed.use = 10, perplexity=30)
# note that you can set do.label=T to help label individual clusters
TSNEPlot(object = tiss, do.label = T)

Check expression of genes of interset.

Dotplots let you see the intensity of exppression and the fraction of cells expressing for each of your genes of interest.

How big are the clusters?

table(tiss@ident)

  0   1   2   3   4   5 
478 324 314 103  32  32 

Which markers identify a specific cluster?

clust.markers <- FindMarkers(object = tiss, ident.1 = 0, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
print(x = head(x= clust.markers, n = 10))
               p_val  avg_diff pct.1 pct.2
Cd2    1.545932e-143 1.5170348 0.921 0.339
Tmsb10 9.639291e-130 0.8109003 0.985 0.740
Shisa5 1.166368e-125 1.2872957 0.950 0.442
Itm2a  2.530852e-101 2.4949185 0.680 0.173
Cd53    1.563433e-99 1.3559720 0.810 0.277
Ccr7    1.204113e-89 1.5242625 0.634 0.135
Pfn1    2.015557e-83 0.6569139 1.000 0.995
Cnn2    1.227621e-82 1.2236462 0.839 0.391
Actg1   1.278102e-75 0.8309641 0.985 0.871
Limd2   8.957058e-71 0.6781611 0.987 0.851

You can also compute all markers for all clusters at once. This may take some time.

#tiss.markers <- FindAllMarkers(object = tiss, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)

Display the top markers you computed above.

#tiss.markers %>% group_by(cluster) %>% top_n(5, avg_diff)

Assigning cell type identity to clusters

At a coarse level, we can use canonical markers to match the unbiased clustering to known cell types:

0: thymocyte_1_mix of DN4_DP_SP 1: thymocyte_2_DP_favoring_CD8 differentiation 2: thymocyte_3_DP_favaroing_CD8 differentiation 3: thymoctye_4_DP_rapidly dividing_favoring CD8 differentation 4: stromal_mesenchymal cell 5: thymocyte_5_DN1

# stash current cluster IDs
tiss <- StashIdent(object = tiss, save.name = "cluster.ids")

# enumerate current cluster IDs and the labels for them
cluster.ids <- c(0, 1, 2, 3, 4, 5)
annotation <-
  c(
  "T cell",
  "T cell",
  "T cell",
  "T cell",
  "mesenchymal stem cell",
  "T cell"
  )
cell_ontology_id <-
  c(
  "CL:0000084",
  "CL:0000084",
  "CL:0000084",
  "CL:0000084",
  "CL:0000134",
  "CL:0000084"
  )

tiss@meta.data[,'annotation'] <- plyr::mapvalues(x = tiss@ident, from = cluster.ids, to = annotation)
tiss@meta.data[,'cell_ontology_id'] <- plyr::mapvalues(x = tiss@ident, from = cluster.ids, to = cell_ontology_id)

tiss@meta.data[tiss@cell.names,'annotation'] <- as.character(tiss@meta.data$annotation)
tiss@meta.data[tiss@cell.names,'cell_ontology_id'] <- as.character(tiss@meta.data$cell_ontology_id)

TSNEPlot(object = tiss, do.label = TRUE, pt.size = 0.5, group.by='annotation')

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = tiss, do.return = TRUE, group.by = "plate.barcode")

Print a table showing the count of cells in each identity category from each plate.

table(as.character(tiss@ident), as.character(tiss@meta.data$plate.barcode))
   
    B000827 B003284 B003285 B003291 MAA000607 MAA000609 MAA000880
  0     244       0       2      36       106        35        55
  1       6       0       3      45       166        57        47
  2      16       1       4     195        10        22        66
  3       3       1       0       8        39        30        22
  4      22       0       0       3         3         1         3
  5       1       5      11       4         7         1         3

Subset and iterate

We can repeat the above analysis on a subset of cells, defined using cluster IDs or some other metadata. This is a good way to drill down and find substructure.

First subset

# Subset data based on cluster id
subtiss <- SubsetData(object = tiss, ident.use = c(0), do.center = F, do.scale = F, cells.use = )

# To subset data based on annotation or other metadata, you can explicitly pass cell names

# anno = 'thymocyte'
# cells.to.use = tiss@cell.names[which(tiss@meta.data$annotation == anno)]
# subtiss <- SubsetData(object = tiss, cells.use = cells.to.use, do.center = F, do.scale = F)
subtiss <- NormalizeData(object = subtiss)
subtiss <- ScaleData(object = subtiss, vars.to.regress = c("nReads", "percent.ribo","Rn45s"))
[1] "Regressing out nReads"       "Regressing out percent.ribo"
[3] "Regressing out Rn45s"       

  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |                                                                 |   1%
  |                                                                       
  |=                                                                |   1%
  |                                                                       
  |=                                                                |   2%
  |                                                                       
  |==                                                               |   3%
  |                                                                       
  |===                                                              |   4%
  |                                                                       
  |===                                                              |   5%
  |                                                                       
  |====                                                             |   5%
  |                                                                       
  |====                                                             |   6%
  |                                                                       
  |====                                                             |   7%
  |                                                                       
  |=====                                                            |   7%
  |                                                                       
  |=====                                                            |   8%
  |                                                                       
  |======                                                           |   9%
  |                                                                       
  |======                                                           |  10%
  |                                                                       
  |=======                                                          |  10%
  |                                                                       
  |=======                                                          |  11%
  |                                                                       
  |========                                                         |  12%
  |                                                                       
  |========                                                         |  13%
  |                                                                       
  |=========                                                        |  14%
  |                                                                       
  |==========                                                       |  15%
  |                                                                       
  |==========                                                       |  16%
  |                                                                       
  |===========                                                      |  16%
  |                                                                       
  |===========                                                      |  17%
  |                                                                       
  |===========                                                      |  18%
  |                                                                       
  |============                                                     |  18%
  |                                                                       
  |============                                                     |  19%
  |                                                                       
  |=============                                                    |  20%
  |                                                                       
  |==============                                                   |  21%
  |                                                                       
  |==============                                                   |  22%
  |                                                                       
  |===============                                                  |  22%
  |                                                                       
  |===============                                                  |  23%
  |                                                                       
  |===============                                                  |  24%
  |                                                                       
  |================                                                 |  24%
  |                                                                       
  |================                                                 |  25%
  |                                                                       
  |=================                                                |  26%
  |                                                                       
  |=================                                                |  27%
  |                                                                       
  |==================                                               |  27%
  |                                                                       
  |==================                                               |  28%
  |                                                                       
  |===================                                              |  29%
  |                                                                       
  |===================                                              |  30%
  |                                                                       
  |====================                                             |  31%
  |                                                                       
  |=====================                                            |  32%
  |                                                                       
  |=====================                                            |  33%
  |                                                                       
  |======================                                           |  33%
  |                                                                       
  |======================                                           |  34%
  |                                                                       
  |=======================                                          |  35%
  |                                                                       
  |=======================                                          |  36%
  |                                                                       
  |========================                                         |  37%
  |                                                                       
  |=========================                                        |  38%
  |                                                                       
  |=========================                                        |  39%
  |                                                                       
  |==========================                                       |  39%
  |                                                                       
  |==========================                                       |  40%
  |                                                                       
  |===========================                                      |  41%
  |                                                                       
  |===========================                                      |  42%
  |                                                                       
  |============================                                     |  43%
  |                                                                       
  |============================                                     |  44%
  |                                                                       
  |=============================                                    |  44%
  |                                                                       
  |=============================                                    |  45%
  |                                                                       
  |==============================                                   |  46%
  |                                                                       
  |===============================                                  |  47%
  |                                                                       
  |===============================                                  |  48%
  |                                                                       
  |================================                                 |  49%
  |                                                                       
  |================================                                 |  50%
  |                                                                       
  |=================================                                |  50%
  |                                                                       
  |=================================                                |  51%
  |                                                                       
  |==================================                               |  52%
  |                                                                       
  |==================================                               |  53%
  |                                                                       
  |===================================                              |  54%
  |                                                                       
  |====================================                             |  55%
  |                                                                       
  |====================================                             |  56%
  |                                                                       
  |=====================================                            |  56%
  |                                                                       
  |=====================================                            |  57%
  |                                                                       
  |======================================                           |  58%
  |                                                                       
  |======================================                           |  59%
  |                                                                       
  |=======================================                          |  60%
  |                                                                       
  |=======================================                          |  61%
  |                                                                       
  |========================================                         |  61%
  |                                                                       
  |========================================                         |  62%
  |                                                                       
  |=========================================                        |  63%
  |                                                                       
  |==========================================                       |  64%
  |                                                                       
  |==========================================                       |  65%
  |                                                                       
  |===========================================                      |  66%
  |                                                                       
  |===========================================                      |  67%
  |                                                                       
  |============================================                     |  67%
  |                                                                       
  |============================================                     |  68%
  |                                                                       
  |=============================================                    |  69%
  |                                                                       
  |==============================================                   |  70%
  |                                                                       
  |==============================================                   |  71%
  |                                                                       
  |===============================================                  |  72%
  |                                                                       
  |===============================================                  |  73%
  |                                                                       
  |================================================                 |  73%
  |                                                                       
  |================================================                 |  74%
  |                                                                       
  |=================================================                |  75%
  |                                                                       
  |=================================================                |  76%
  |                                                                       
  |==================================================               |  76%
  |                                                                       
  |==================================================               |  77%
  |                                                                       
  |==================================================               |  78%
  |                                                                       
  |===================================================              |  78%
  |                                                                       
  |===================================================              |  79%
  |                                                                       
  |====================================================             |  80%
  |                                                                       
  |=====================================================            |  81%
  |                                                                       
  |=====================================================            |  82%
  |                                                                       
  |======================================================           |  82%
  |                                                                       
  |======================================================           |  83%
  |                                                                       
  |======================================================           |  84%
  |                                                                       
  |=======================================================          |  84%
  |                                                                       
  |=======================================================          |  85%
  |                                                                       
  |========================================================         |  86%
  |                                                                       
  |=========================================================        |  87%
  |                                                                       
  |=========================================================        |  88%
  |                                                                       
  |==========================================================       |  89%
  |                                                                       
  |==========================================================       |  90%
  |                                                                       
  |===========================================================      |  90%
  |                                                                       
  |===========================================================      |  91%
  |                                                                       
  |============================================================     |  92%
  |                                                                       
  |============================================================     |  93%
  |                                                                       
  |=============================================================    |  93%
  |                                                                       
  |=============================================================    |  94%
  |                                                                       
  |=============================================================    |  95%
  |                                                                       
  |==============================================================   |  95%
  |                                                                       
  |==============================================================   |  96%
  |                                                                       
  |===============================================================  |  97%
  |                                                                       
  |================================================================ |  98%
  |                                                                       
  |================================================================ |  99%
  |                                                                       
  |=================================================================|  99%
  |                                                                       
  |=================================================================| 100%
[1] "Scaling data matrix"

  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=================================================================| 100%
subtiss <- FindVariableGenes(object = subtiss, do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.8)

subtiss <- RunPCA(object = subtiss, pcs.compute = 20)
[1] "PC1"
 [1] "Satb1"    "Myb"      "Itm2a"    "Sox4"     "Tcf7"     "Tox"     
 [7] "Cd24a"    "Ccr9"     "Sept11"   "Hivep3"   "Cd27"     "Slc29a1" 
[13] "Vamp1"    "Ldhb"     "Lars2"    "Jarid2"   "Hspa4l"   "Colq"    
[19] "BC024659" "Sf3b3"    "Pfkp"     "Cnn3"     "Arpp21"   "Nedd4"   
[25] "Tacc2"    "Ikzf2"    "Mtf2"     "Camk4"    "Ppan"     "Kcnq1ot1"
[1] ""
 [1] "H2-K1"    "B2m"      "Ms4a4b"   "Shisa5"   "Gimap3"   "AW112010"
 [7] "Stat1"    "Ms4a6b"   "Ltb"      "Tgtp2"    "Itgb7"    "Ifit1"   
[13] "Zbp1"     "Ly6a"     "Ccr6"     "H2-Q6"    "Tgtp1"    "Irgm1"   
[19] "Rln3"     "Foxp3"    "Capg"     "Pydc3"    "Dhx58"    "S1pr1"   
[25] "Ctla4"    "Ccr7"     "Tnfrsf4"  "Ifi47"    "Ccnd2"    "Tap1"    
[1] ""
[1] ""
[1] "PC2"
 [1] "Cd8b1"         "Cd8a"          "Ccr9"          "Dntt"         
 [5] "Bcl11b"        "Slc16a5"       "Satb1"         "Tcf7"         
 [9] "1190002H23Rik" "Arpp21"        "Rmnd5a"        "Rag1"         
[13] "2610019F03Rik" "Lpar6"         "Fbxl12"        "Aqp11"        
[17] "Rcbtb2"        "Tgtp1"         "Ssbp2"         "Pdk1"         
[21] "Tube1"         "Gbp8"          "Trib2"         "Zcchc11"      
[25] "Rag2"          "Kcnh3"         "Prkcb"         "Nkg7"         
[29] "Rhoh"          "Mns1"         
[1] ""
 [1] "Tnfrsf9"       "Srgn"          "Cd5"           "Pdcd1"        
 [5] "Nr4a1"         "Tnfrsf4"       "Stx11"         "Nfkbid"       
 [9] "Ikzf2"         "Tagap"         "Tigit"         "Rln3"         
[13] "Tnfrsf18"      "Nr4a3"         "Cd6"           "Itm2a"        
[17] "Hivep3"        "Gadd45b"       "Ikzf3"         "Ccr8"         
[21] "Acot7"         "Ccr6"          "Cytip"         "Gata3"        
[25] "A430093F15Rik" "Chst2"         "Ctla4"         "Sdcbp2"       
[29] "Ephx1"         "Icos"         
[1] ""
[1] ""
[1] "PC3"
 [1] "Ldhb"          "Nfkbia"        "Gata3"         "Lpar6"        
 [5] "Cnn3"          "Btg2"          "Dusp1"         "Copz1"        
 [9] "Ltb"           "Sdc4"          "Itm2a"         "Aqp11"        
[13] "Bcl2l11"       "Ttc19"         "Lyrm5"         "Dcn"          
[17] "Tspan32"       "Zfp689"        "Fam118b"       "Commd10"      
[21] "Nmnat3"        "8430410A17Rik" "Cd27"          "Fbxl12"       
[25] "Asb6"          "Acp5"          "H2-Q2"         "Bambi-ps1"    
[29] "Tab1"          "Rad9"         
[1] ""
 [1] "Lars2"    "Nkg7"     "Esyt1"    "Atp1a1"   "Runx3"    "Itgae"   
 [7] "Pydc3"    "Ash1l"    "Gpr114"   "Eif2s3y"  "Tgtp1"    "Heatr1"  
[13] "Mthfd1"   "Lcp1"     "Stat1"    "Gm4759"   "Tgtp2"    "Nampt"   
[19] "Gemin4"   "Akna"     "Heatr3"   "Kcnq1ot1" "Ctsw"     "Epm2aip1"
[25] "Irgm1"    "Top2b"    "Eef2"     "Cmtm6"    "Ptk2b"    "Nol9"    
[1] ""
[1] ""
[1] "PC4"
 [1] "Itm2a"   "Id2"     "Tuba4a"  "Ccr7"    "Satb1"   "Il7r"    "Cytip"  
 [8] "Acvrl1"  "Gpatch1" "Sgms1"   "Bcl2"    "Bzw2"    "Samhd1"  "Tbl1x"  
[15] "Als2cl"  "Gsn"     "Lef1"    "Tnfsf11" "Crtc1"   "Bcl11b"  "Folr4"  
[22] "Arhgef6" "Telo2"   "Stradb"  "Gata3"   "Tecpr1"  "Arhgef4" "Shc1"   
[29] "Xylt2"   "Mn1"    
[1] ""
 [1] "Ikzf2"     "Cd8a"      "Cd8b1"     "Myb"       "Colq"     
 [6] "Arpp21"    "AW112010"  "Nkg7"      "Srgn"      "Dntt"     
[11] "Rmnd5a"    "Itgae"     "Aqp11"     "Ifngr1"    "Cd24a"    
[16] "Tigit"     "Ly6d"      "Tnfrsf9"   "Sdc4"      "Tagap"    
[21] "Slc16a5"   "Cst7"      "Rag1"      "H2-Q6"     "Nfkbia"   
[26] "Ly6e"      "Tagln2"    "Lig4"      "Trp53inp1" "Stx11"    
[1] ""
[1] ""
[1] "PC5"
 [1] "Pld3"          "Nkg7"          "Cct3"          "1190002H23Rik"
 [5] "Ptpn6"         "Tagln2"        "Bcl2"          "Prep"         
 [9] "Mcm5"          "Gpr114"        "Cirh1a"        "Hivep3"       
[13] "Smad2"         "Id3"           "Cd8a"          "Lcp1"         
[17] "Ddx3x"         "Runx3"         "Rpn2"          "Tuba4a"       
[21] "Nampt"         "Ppat"          "Filip1l"       "Cd8b1"        
[25] "Anapc5"        "Pold1"         "Sla"           "Rrp1b"        
[29] "Agpat2"        "Tubb3"        
[1] ""
 [1] "E430025E21Rik" "Csnk2a2"       "Ap2a1"         "Zfp592"       
 [5] "Glt25d1"       "Aff1"          "Terf2"         "Arhgap17"     
 [9] "Cpsf4"         "Fam132a"       "Spred1"        "Zfp192"       
[13] "Epm2aip1"      "Gfm2"          "Cog6"          "Rrbp1"        
[17] "Zfp85-rs1"     "Zswim4"        "Adcy6"         "BC024659"     
[21] "Zfp628"        "Scai"          "Ash1l"         "Phf8"         
[25] "Mtap4"         "Edc4"          "Synj1"         "Sall2"        
[29] "Terf1"         "Rtf1"         
[1] ""
[1] ""
subtiss <- ProjectPCA(object = subtiss, do.print = FALSE)

Run Principal Component Analysis.

subtiss <- RunPCA(object = subtiss, do.print = FALSE)
subtiss <- ProjectPCA(object = subtiss, do.print = FALSE)
# If this fails for your subset, it may be that cells.use is more cells than you have left! Try reducing it.
PCHeatmap(object = subtiss, pc.use = 1:3, cells.use = 200, do.balanced = TRUE, label.columns = FALSE, num.genes = 12)

Later on (in FindClusters and TSNE) you will pick a number of principal components to use. This has the effect of keeping the major directions of variation in the data and, ideally, supressing noise. There is no correct answer to the number to use, but a decent rule of thumb is to go until the plot plateaus.

PCElbowPlot(object = subtiss)

Choose the number of principal components to use.

# Set number of principal components. 
sub.n.pcs = 6

The clustering is performed based on a nearest neighbors graph. Cells that have similar expression will be joined together. The Louvain algorithm looks for groups of cells with high modularity–more connections within the group than between groups. The resolution parameter determines the scale…higher resolution will give more clusters, lower resolution will give fewer.

# Set resolution 
sub.res.used <- 1

subtiss <- FindClusters(object = subtiss, reduction.type = "pca", dims.use = 1:sub.n.pcs, 
    resolution = sub.res.used, print.output = 0, save.SNN = TRUE)

To visualize

# If cells are too spread out, you can raise the perplexity. If you have few cells, try a lower perplexity (but never less than 10).
subtiss <- RunTSNE(object = subtiss, dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=20)
# note that you can set do.label=T to help label individual clusters
TSNEPlot(object = subtiss, do.label = T)

subtiss.markers <- FindAllMarkers(object = subtiss, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
subtiss.markers %>% group_by(cluster) %>% top_n(6, avg_diff)

Check expression of genes of interset.

genes_to_check = c('Cd4','Cd8a','Cd53','Cd44','Cd7','Cd2','Il2ra','Rag1','Zap70','Dntt','Il7r','Cd69','Pdcd1','Shisa5','Cd5','Lef1','Ccr7','Ptcra','Itm2a','Cd28','Cd3e')

FeaturePlot(subtiss, genes_to_check, pt.size = 1)

Dotplots let you see the intensity of exppression and the fraction of cells expressing for each of your genes of interest.

How big are the clusters?

table(subtiss@ident)

  0   1   2   3   4   5 
104  97  92  79  62  44 

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = subtiss, do.return = TRUE, group.by = "plate.barcode")

Print a table showing the count of cells in each identity category from each plate.

table(as.character(subtiss@ident), as.character(subtiss@meta.data$plate.barcode))
   
    B000827 B003285 B003291 MAA000607 MAA000609 MAA000880
  0      58       0       1        25         6        14
  1      78       0       5         4         5         5
  2      50       2       8        10         7        15
  3      24       0       5        29         8        13
  4      32       0       1        18         5         6
  5       2       0      16        20         4         2

Assigning subannotations

For the subsets, we produce subannotations. These will be written back as metadata in the original object, so we can see all subannotations together.

If some of the clusters you find in the subset deserve additional annotation, you can add that right here. Use NA for clusters for which no subannotation is needed.

subcluster.ids <- c(0, 1, 2,3,4,5)
subannotation <- c("immature_SP_CD4","immature_SP_CD4","DN4","immature_SP_CD4","Immature_SP_CD8","DP")

subtiss@meta.data[,'subannotation'] <- plyr::mapvalues(x = subtiss@ident, from = subcluster.ids, to = subannotation)

tiss@meta.data[subtiss@cell.names,'subannotation'] <- as.character(subtiss@meta.data$subannotation)

TSNEPlot(object = subtiss, do.label = TRUE, pt.size = 0.5, group.by='subannotation')

Save the Robject for later

When you save the annotated tissue, please give it a name.

filename = here('00_data_ingest', 'tissue_seurat_robj', 
                     paste0(tissue_of_interest, "_seurat_tiss.Robj"))
print(filename)
[1] "/Users/olgabot/code/tabula-muris/00_data_ingest/tissue_seurat_robj/Thymus_seurat_tiss.Robj"
save(tiss, file=filename)
# To reload a saved object
# filename = here('00_data_ingest', 'tissue_seurat_robj', 
#                      paste0(tissue_of_interest, "_seurat_tiss.Robj"))
# load(file=filename)

Export the final metadata

So that Biohub can easily combine all your annotations, please export them as a simple csv.

head(tiss@meta.data)
filename = here('00_data_ingest', 'tissue_annotation_csv', 
                     paste0(tissue_of_interest, "_annotation.csv"))
write.csv(tiss@meta.data[,c('plate.barcode','annotation','cell_ontology_id')], file=filename)
LS0tCnRpdGxlOiAiVGh5bXVzIEZBQ1MgTm90ZWJvb2siCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkVudGVyIHRoZSBkaXJlY3Rvcnkgb2YgdGhlIG1hY2EgZm9sZGVyIG9uIHlvdXIgZHJpdmUgYW5kIHRoZSBuYW1lIG9mIHRoZSB0aXNzdWUgeW91IHdhbnQgdG8gYW5hbHl6ZS4KCmBgYHtyfQp0aXNzdWVfb2ZfaW50ZXJlc3QgPSAiVGh5bXVzIgpgYGAKCkxvYWQgdGhlIHJlcXVpc2l0ZSBwYWNrYWdlcyBhbmQgc29tZSBhZGRpdGlvbmFsIGhlbHBlciBmdW5jdGlvbnMuCgpgYGB7cn0KbGlicmFyeShoZXJlKQpsaWJyYXJ5KHVzZWZ1bCkKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoTWF0cml4KQoKc2F2ZV9kaXIgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICd0aXNzdWVfcm9iaicpCmBgYAoKCgpgYGB7cn0KIyByZWFkIHRoZSBtZXRhZGF0YSB0byBnZXQgdGhlIHBsYXRlcyB3ZSB3YW50CnBsYXRlX21ldGFkYXRhX2ZpbGVuYW1lID0gaGVyZSgnMDBfZGF0YV9pbmdlc3QnLCAnZmFjc19yYXdfZGF0YScsICdtZXRhZGF0YV9GQUNTLmNzdicpCgpwbGF0ZV9tZXRhZGF0YSA8LSByZWFkLmNzdihwbGF0ZV9tZXRhZGF0YV9maWxlbmFtZSwgc2VwPSIsIiwgaGVhZGVyID0gVFJVRSkKY29sbmFtZXMocGxhdGVfbWV0YWRhdGEpWzFdIDwtICJwbGF0ZS5iYXJjb2RlIgpwbGF0ZV9tZXRhZGF0YQpgYGAKClN1YnNldCB0aGUgbWV0YWRhdGEgb24gdGhlIHRpc3N1ZS4KCmBgYHtyfQp0aXNzdWVfcGxhdGVzID0gZmlsdGVyKHBsYXRlX21ldGFkYXRhLCB0aXNzdWUgPT0gdGlzc3VlX29mX2ludGVyZXN0KVssYygncGxhdGUuYmFyY29kZScsJ3Rpc3N1ZScsJ3N1YnRpc3N1ZScsJ21vdXNlLnNleCcpXQp0aXNzdWVfcGxhdGVzCmBgYAoKTG9hZCB0aGUgcmVhZCBjb3VudCBkYXRhLgpgYGB7cn0KI0xvYWQgdGhlIGdlbmUgbmFtZXMgYW5kIHNldCB0aGUgbWV0YWRhdGEgY29sdW1ucyBieSBvcGVuaW5nIHRoZSBmaXJzdCBmaWxlCmZpbGVuYW1lID0gaGVyZSgnMDBfZGF0YV9pbmdlc3QnLCAnZmFjc19yYXdfZGF0YScsICdGQUNTJywgcGFzdGUwKHRpc3N1ZV9vZl9pbnRlcmVzdCwgJy1jb3VudHMuY3N2JykpCgpyYXcuZGF0YSA9IHJlYWQuY3N2KGZpbGVuYW1lLCBzZXA9IiwiLCByb3cubmFtZXM9MSkKIyByYXcuZGF0YSA9IGRhdGEuZnJhbWUocm93Lm5hbWVzID0gcm93bmFtZXMocmF3LmRhdGEpKQpjb3JuZXIocmF3LmRhdGEpCmBgYApNYWtlIGEgdmVjdG9yIG9mIHBsYXRlIGJhcmNvZGVzIGZvciBlYWNoIGNlbGwKCmBgYHtyfQpwbGF0ZS5iYXJjb2RlcyA9IGxhcHBseShjb2xuYW1lcyhyYXcuZGF0YSksIGZ1bmN0aW9uKHgpIHN0cnNwbGl0KHN0cnNwbGl0KHgsICJfIilbWzFdXVsxXSwgJy4nLCBmaXhlZD1UUlVFKVtbMV1dWzJdKQpoZWFkKHBsYXRlLmJhcmNvZGVzKQpgYGAKClVzZSBvbmx5IHRoZSBtZXRhZGF0YSByb3dzIGNvcnJlc3BvbmRpbmcgdG8gQmxhZGRlciBwbGF0ZXMuIE1ha2UgYSBwbGF0ZSBiYXJjb2RlIGRhdGFmcmFtZSB0byAiZXhwYW5kIiB0aGUgcGVyLXBsYXRlIG1ldGFkYXRhIHRvIGJlIHBlci1jZWxsLgpgYGB7cn0KYmFyY29kZS5kZiA9IHQuZGF0YS5mcmFtZShhcy5kYXRhLmZyYW1lKHBsYXRlLmJhcmNvZGVzKSkKCnJvd25hbWVzKGJhcmNvZGUuZGYpID0gY29sbmFtZXMocmF3LmRhdGEpCmNvbG5hbWVzKGJhcmNvZGUuZGYpID0gYygncGxhdGUuYmFyY29kZScpCmhlYWQoYmFyY29kZS5kZikKCnJuYW1lcyA9IHJvdy5uYW1lcyhiYXJjb2RlLmRmKQptZXRhLmRhdGEgPC0gbWVyZ2UoYmFyY29kZS5kZiwgcGxhdGVfbWV0YWRhdGEsIGJ5PSdwbGF0ZS5iYXJjb2RlJywgc29ydCA9IEYpCnJvdy5uYW1lcyhtZXRhLmRhdGEpIDwtIHJuYW1lcwoKIyBTb3J0IGNlbGxzIGJ5IHBsYXRlIGJhcmNvZGUgYmVjYXVzZSB0aGF0J3MgaG93IHRoZSBkYXRhIHdhcyBvcmlnaW5hbGx5Cm1ldGEuZGF0YSA9IG1ldGEuZGF0YVtvcmRlcihtZXRhLmRhdGEkcGxhdGUuYmFyY29kZSksIF0KY29ybmVyKG1ldGEuZGF0YSkKcmF3LmRhdGEgPSByYXcuZGF0YVssIHJvd25hbWVzKG1ldGEuZGF0YSldCmNvcm5lcihyYXcuZGF0YSkKYGBgCgpQcm9jZXNzIHRoZSByYXcgZGF0YSBhbmQgbG9hZCBpdCBpbnRvIHRoZSBTZXVyYXQgb2JqZWN0LgoKYGBge3J9CiMgRmluZCBFUkNDJ3MsIGNvbXB1dGUgdGhlIHBlcmNlbnQgRVJDQywgYW5kIGRyb3AgdGhlbSBmcm9tIHRoZSByYXcgZGF0YS4KZXJjY3MgPC0gZ3JlcChwYXR0ZXJuID0gIl5FUkNDLSIsIHggPSByb3duYW1lcyh4ID0gcmF3LmRhdGEpLCB2YWx1ZSA9IFRSVUUpCnBlcmNlbnQuZXJjYyA8LSBNYXRyaXg6OmNvbFN1bXMocmF3LmRhdGFbZXJjY3MsIF0pL01hdHJpeDo6Y29sU3VtcyhyYXcuZGF0YSkKZXJjYy5pbmRleCA8LSBncmVwKHBhdHRlcm4gPSAiXkVSQ0MtIiwgeCA9IHJvd25hbWVzKHggPSByYXcuZGF0YSksIHZhbHVlID0gRkFMU0UpCnJhdy5kYXRhIDwtIHJhdy5kYXRhWy1lcmNjLmluZGV4LF0KCiMgQ3JlYXRlIHRoZSBTZXVyYXQgb2JqZWN0IHdpdGggYWxsIHRoZSBkYXRhCnRpc3MgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KHJhdy5kYXRhID0gcmF3LmRhdGEsIHByb2plY3QgPSB0aXNzdWVfb2ZfaW50ZXJlc3QsIAogICAgICAgICAgICAgICAgICAgIG1pbi5jZWxscyA9IDUsIG1pbi5nZW5lcyA9IDUpCgp0aXNzIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IHRpc3MsIG1ldGEuZGF0YSkKdGlzcyA8LSBBZGRNZXRhRGF0YShvYmplY3QgPSB0aXNzLCBwZXJjZW50LmVyY2MsIGNvbC5uYW1lID0gInBlcmNlbnQuZXJjYyIpCiMgQ2hhbmdlIGRlZmF1bHQgbmFtZSBmb3Igc3VtcyBvZiBjb3VudHMgZnJvbSBuVU1JIHRvIG5SZWFkcwpjb2xuYW1lcyh0aXNzQG1ldGEuZGF0YSlbY29sbmFtZXModGlzc0BtZXRhLmRhdGEpID09ICduVU1JJ10gPC0gJ25SZWFkcycKCiMgQ3JlYXRlIG1ldGFkYXRhIGNvbHVtbnMgZm9yIGFubm90YXRpb25zIGFuZCBzdWJhbm5vdGF0aW9ucwp0aXNzQG1ldGEuZGF0YVssJ2Fubm90YXRpb24nXSA8LSBOQQp0aXNzQG1ldGEuZGF0YVssJ3N1YmFubm90YXRpb24nXSA8LSBOQQpgYGAKCgpDYWxjdWxhdGUgcGVyY2VudCByaWJvc29tYWwgZ2VuZXMuCgpgYGB7cn0Kcmliby5nZW5lcyA8LSBncmVwKHBhdHRlcm4gPSAiXlJwW3NsXVtbOmRpZ2l0Ol1dIiwgeCA9IHJvd25hbWVzKHggPSB0aXNzQGRhdGEpLCB2YWx1ZSA9IFRSVUUpCnBlcmNlbnQucmlibyA8LSBNYXRyaXg6OmNvbFN1bXModGlzc0ByYXcuZGF0YVtyaWJvLmdlbmVzLCBdKS9NYXRyaXg6OmNvbFN1bXModGlzc0ByYXcuZGF0YSkKdGlzcyA8LSBBZGRNZXRhRGF0YShvYmplY3QgPSB0aXNzLCBtZXRhZGF0YSA9IHBlcmNlbnQucmlibywgY29sLm5hbWUgPSAicGVyY2VudC5yaWJvIikKYGBgCgpBIHNhbml0eSBjaGVjazogZ2VuZXMgcGVyIGNlbGwgdnMgcmVhZHMgcGVyIGNlbGwuCgpgYGB7cn0KR2VuZVBsb3Qob2JqZWN0ID0gdGlzcywgZ2VuZTEgPSAiblJlYWRzIiwgZ2VuZTIgPSAibkdlbmUiLCB1c2UucmF3PVQpCmBgYAoKRmlsdGVyIG91dCBjZWxscyB3aXRoIGZldyByZWFkcyBhbmQgZmV3IGdlbmVzLgoKYGBge3J9CnRpc3MgPC0gRmlsdGVyQ2VsbHMob2JqZWN0ID0gdGlzcywgc3Vic2V0Lm5hbWVzID0gYygibkdlbmUiLCAiblJlYWRzIiksIAogICAgbG93LnRocmVzaG9sZHMgPSBjKDUwMCwgNTAwMDApLCBoaWdoLnRocmVzaG9sZHMgPSBjKDI1MDAwLCAyMDAwMDAwKSkKYGBgCgoKTm9ybWFsaXplIHRoZSBkYXRhLCB0aGVuIHJlZ3Jlc3Mgb3V0IGNvcnJlbGF0aW9uIHdpdGggdG90YWwgcmVhZHMKYGBge3J9CnRpc3MgPC0gTm9ybWFsaXplRGF0YShvYmplY3QgPSB0aXNzKQp0aXNzIDwtIFNjYWxlRGF0YShvYmplY3QgPSB0aXNzLCB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJuUmVhZHMiLCAicGVyY2VudC5yaWJvIiwiUm40NXMiKSkKdGlzcyA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSB0aXNzLCBkby5wbG90ID0gVFJVRSwgeC5oaWdoLmN1dG9mZiA9IEluZiwgeS5jdXRvZmYgPSAwLjUpCmBgYAoKClJ1biBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzLgpgYGB7cn0KdGlzcyA8LSBSdW5QQ0Eob2JqZWN0ID0gdGlzcywgZG8ucHJpbnQgPSBGQUxTRSkKdGlzcyA8LSBQcm9qZWN0UENBKG9iamVjdCA9IHRpc3MsIGRvLnByaW50ID0gRkFMU0UpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTh9ClBDSGVhdG1hcChvYmplY3QgPSB0aXNzLCBwYy51c2UgPSAxOjMsIGNlbGxzLnVzZSA9IDUwMCwgZG8uYmFsYW5jZWQgPSBUUlVFLCBsYWJlbC5jb2x1bW5zID0gRkFMU0UsIG51bS5nZW5lcyA9IDgpCmBgYAoKTGF0ZXIgb24gKGluIEZpbmRDbHVzdGVycyBhbmQgVFNORSkgeW91IHdpbGwgcGljayBhIG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cyB0byB1c2UuIFRoaXMgaGFzIHRoZSBlZmZlY3Qgb2Yga2VlcGluZyB0aGUgbWFqb3IgZGlyZWN0aW9ucyBvZiB2YXJpYXRpb24gaW4gdGhlIGRhdGEgYW5kLCBpZGVhbGx5LCBzdXByZXNzaW5nIG5vaXNlLiBUaGVyZSBpcyBubyBjb3JyZWN0IGFuc3dlciB0byB0aGUgbnVtYmVyIHRvIHVzZSwgYnV0IGEgZGVjZW50IHJ1bGUgb2YgdGh1bWIgaXMgdG8gZ28gdW50aWwgdGhlIHBsb3QgcGxhdGVhdXMuCgpgYGB7cn0KUENFbGJvd1Bsb3Qob2JqZWN0ID0gdGlzcykKYGBgCgpDaG9vc2UgdGhlIG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cyB0byB1c2UuCmBgYHtyfQojIFNldCBudW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHMuIApuLnBjcyA9IDEwCmBgYAoKClRoZSBjbHVzdGVyaW5nIGlzIHBlcmZvcm1lZCBiYXNlZCBvbiBhIG5lYXJlc3QgbmVpZ2hib3JzIGdyYXBoLiBDZWxscyB0aGF0IGhhdmUgc2ltaWxhciBleHByZXNzaW9uIHdpbGwgYmUgam9pbmVkIHRvZ2V0aGVyLiBUaGUgTG91dmFpbiBhbGdvcml0aG0gbG9va3MgZm9yIGdyb3VwcyBvZiBjZWxscyB3aXRoIGhpZ2ggbW9kdWxhcml0eS0tbW9yZSBjb25uZWN0aW9ucyB3aXRoaW4gdGhlIGdyb3VwIHRoYW4gYmV0d2VlbiBncm91cHMuIFRoZSByZXNvbHV0aW9uIHBhcmFtZXRlciBkZXRlcm1pbmVzIHRoZSBzY2FsZS4uLmhpZ2hlciByZXNvbHV0aW9uIHdpbGwgZ2l2ZSBtb3JlIGNsdXN0ZXJzLCBsb3dlciByZXNvbHV0aW9uIHdpbGwgZ2l2ZSBmZXdlci4KCkZvciB0aGUgdG9wLWxldmVsIGNsdXN0ZXJpbmcsIGFpbSB0byB1bmRlci1jbHVzdGVyIGluc3RlYWQgb2Ygb3Zlci1jbHVzdGVyLiBJdCB3aWxsIGJlIGVhc3kgdG8gc3Vic2V0IGdyb3VwcyBhbmQgZnVydGhlciBhbmFseXplIHRoZW0gYmVsb3cuCgpgYGB7cn0KIyBTZXQgcmVzb2x1dGlvbiAKcmVzLnVzZWQgPC0gMC41Cgp0aXNzIDwtIEZpbmRDbHVzdGVycyhvYmplY3QgPSB0aXNzLCByZWR1Y3Rpb24udHlwZSA9ICJwY2EiLCBkaW1zLnVzZSA9IDE6bi5wY3MsIAogICAgcmVzb2x1dGlvbiA9IHJlcy51c2VkLCBwcmludC5vdXRwdXQgPSAwLCBzYXZlLlNOTiA9IFRSVUUpCmBgYAoKVG8gdmlzdWFsaXplIApgYGB7cn0KIyBJZiBjZWxscyBhcmUgdG9vIHNwcmVhZCBvdXQsIHlvdSBjYW4gcmFpc2UgdGhlIHBlcnBsZXhpdHkuIElmIHlvdSBoYXZlIGZldyBjZWxscywgdHJ5IGEgbG93ZXIgcGVycGxleGl0eSAoYnV0IG5ldmVyIGxlc3MgdGhhbiAxMCkuCnRpc3MgPC0gUnVuVFNORShvYmplY3QgPSB0aXNzLCBkaW1zLnVzZSA9IDE6bi5wY3MsIHNlZWQudXNlID0gMTAsIHBlcnBsZXhpdHk9MzApCmBgYAoKYGBge3J9CiMgbm90ZSB0aGF0IHlvdSBjYW4gc2V0IGRvLmxhYmVsPVQgdG8gaGVscCBsYWJlbCBpbmRpdmlkdWFsIGNsdXN0ZXJzClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLmxhYmVsID0gVCkKYGBgCgpDaGVjayBleHByZXNzaW9uIG9mIGdlbmVzIG9mIGludGVyc2V0LgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD04fQpnZW5lc190b19jaGVjayA9IGMoJ1ZpbScsJ0tydDUnLCdLcnQ4JywnUHRwcmMnLCdFcGNhbScsJ0gyLUFiMScsJ0gyLUFhJywnQ2QzZScsJ0NkM2QnLCdDZDNnJywnQ2Q0JywnQ2Q4YScsJ0NkOGIxJywnRXRzMScsJ0NkNDQnLCdJbDJyYScpCiNnZW5lc190b19jaGVjayA9IGMoJ0FsYicsICdDeXAyZjInLCAnQ3lwMmUxJywgJ0hhbXAnKQoKRmVhdHVyZVBsb3QodGlzcywgZ2VuZXNfdG9fY2hlY2ssIHB0LnNpemUgPSAxLCBuQ29sID0gMykKYGBgCgpEb3RwbG90cyBsZXQgeW91IHNlZSB0aGUgaW50ZW5zaXR5IG9mIGV4cHByZXNzaW9uIGFuZCB0aGUgZnJhY3Rpb24gb2YgY2VsbHMgZXhwcmVzc2luZyBmb3IgZWFjaCBvZiB5b3VyIGdlbmVzIG9mIGludGVyZXN0LgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTIwfQojIFRvIGNoYW5nZSB0aGUgeS1heGlzIHRvIHNob3cgcmF3IGNvdW50cywgYWRkIHVzZS5yYXcgPSBULgpEb3RQbG90KHRpc3MsIGdlbmVzX3RvX2NoZWNrLCBwbG90LmxlZ2VuZCA9IFQpCmBgYAoKSG93IGJpZyBhcmUgdGhlIGNsdXN0ZXJzPwpgYGB7cn0KdGFibGUodGlzc0BpZGVudCkKYGBgCgpXaGljaCBtYXJrZXJzIGlkZW50aWZ5IGEgc3BlY2lmaWMgY2x1c3Rlcj8KCmBgYHtyfQpjbHVzdC5tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHRpc3MsIGlkZW50LjEgPSAwLCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCB0aHJlc2gudXNlID0gMC4yNSkKYGBgCgpgYGB7cn0KcHJpbnQoeCA9IGhlYWQoeD0gY2x1c3QubWFya2VycywgbiA9IDEwKSkKYGBgCgpZb3UgY2FuIGFsc28gY29tcHV0ZSBhbGwgbWFya2VycyBmb3IgYWxsIGNsdXN0ZXJzIGF0IG9uY2UuIFRoaXMgbWF5IHRha2Ugc29tZSB0aW1lLgpgYGB7cn0KI3Rpc3MubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSB0aXNzLCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCB0aHJlc2gudXNlID0gMC4yNSkKYGBgCgpEaXNwbGF5IHRoZSB0b3AgbWFya2VycyB5b3UgY29tcHV0ZWQgYWJvdmUuCmBgYHtyfQojdGlzcy5tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24oNSwgYXZnX2RpZmYpCmBgYAoKIyMgQXNzaWduaW5nIGNlbGwgdHlwZSBpZGVudGl0eSB0byBjbHVzdGVycwoKQXQgYSBjb2Fyc2UgbGV2ZWwsIHdlIGNhbiB1c2UgY2Fub25pY2FsIG1hcmtlcnMgdG8gbWF0Y2ggdGhlIHVuYmlhc2VkIGNsdXN0ZXJpbmcgdG8ga25vd24gY2VsbCB0eXBlczoKCjA6IHRoeW1vY3l0ZV8xX21peCBvZiBETjRfRFBfU1AgCjE6IHRoeW1vY3l0ZV8yX0RQX2Zhdm9yaW5nX0NEOCBkaWZmZXJlbnRpYXRpb24KMjogdGh5bW9jeXRlXzNfRFBfZmF2YXJvaW5nX0NEOCBkaWZmZXJlbnRpYXRpb24gCjM6IHRoeW1vY3R5ZV80X0RQX3JhcGlkbHkgZGl2aWRpbmdfZmF2b3JpbmcgQ0Q4IGRpZmZlcmVudGF0aW9uIAo0OiBzdHJvbWFsX21lc2VuY2h5bWFsIGNlbGwgCjU6IHRoeW1vY3l0ZV81X0ROMSAKCgoKCgpgYGB7cn0KIyBzdGFzaCBjdXJyZW50IGNsdXN0ZXIgSURzCnRpc3MgPC0gU3Rhc2hJZGVudChvYmplY3QgPSB0aXNzLCBzYXZlLm5hbWUgPSAiY2x1c3Rlci5pZHMiKQoKIyBlbnVtZXJhdGUgY3VycmVudCBjbHVzdGVyIElEcyBhbmQgdGhlIGxhYmVscyBmb3IgdGhlbQpjbHVzdGVyLmlkcyA8LSBjKDAsIDEsIDIsIDMsIDQsIDUpCmFubm90YXRpb24gPC0KICBjKAogICJUIGNlbGwiLAogICJUIGNlbGwiLAogICJUIGNlbGwiLAogICJUIGNlbGwiLAogICJtZXNlbmNoeW1hbCBzdGVtIGNlbGwiLAogICJUIGNlbGwiCiAgKQpjZWxsX29udG9sb2d5X2lkIDwtCiAgYygKICAiQ0w6MDAwMDA4NCIsCiAgIkNMOjAwMDAwODQiLAogICJDTDowMDAwMDg0IiwKICAiQ0w6MDAwMDA4NCIsCiAgIkNMOjAwMDAxMzQiLAogICJDTDowMDAwMDg0IgogICkKCnRpc3NAbWV0YS5kYXRhWywnYW5ub3RhdGlvbiddIDwtIHBseXI6Om1hcHZhbHVlcyh4ID0gdGlzc0BpZGVudCwgZnJvbSA9IGNsdXN0ZXIuaWRzLCB0byA9IGFubm90YXRpb24pCnRpc3NAbWV0YS5kYXRhWywnY2VsbF9vbnRvbG9neV9pZCddIDwtIHBseXI6Om1hcHZhbHVlcyh4ID0gdGlzc0BpZGVudCwgZnJvbSA9IGNsdXN0ZXIuaWRzLCB0byA9IGNlbGxfb250b2xvZ3lfaWQpCgp0aXNzQG1ldGEuZGF0YVt0aXNzQGNlbGwubmFtZXMsJ2Fubm90YXRpb24nXSA8LSBhcy5jaGFyYWN0ZXIodGlzc0BtZXRhLmRhdGEkYW5ub3RhdGlvbikKdGlzc0BtZXRhLmRhdGFbdGlzc0BjZWxsLm5hbWVzLCdjZWxsX29udG9sb2d5X2lkJ10gPC0gYXMuY2hhcmFjdGVyKHRpc3NAbWV0YS5kYXRhJGNlbGxfb250b2xvZ3lfaWQpCgpUU05FUGxvdChvYmplY3QgPSB0aXNzLCBkby5sYWJlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjUsIGdyb3VwLmJ5PSdhbm5vdGF0aW9uJykKYGBgCgoKIyMgQ2hlY2tpbmcgZm9yIGJhdGNoIGVmZmVjdHMKCgpDb2xvciBieSBtZXRhZGF0YSwgbGlrZSBwbGF0ZSBiYXJjb2RlLCB0byBjaGVjayBmb3IgYmF0Y2ggZWZmZWN0cy4KYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gInBsYXRlLmJhcmNvZGUiKQpgYGAKClByaW50IGEgdGFibGUgc2hvd2luZyB0aGUgY291bnQgb2YgY2VsbHMgaW4gZWFjaCBpZGVudGl0eSBjYXRlZ29yeSBmcm9tIGVhY2ggcGxhdGUuCgpgYGB7cn0KdGFibGUoYXMuY2hhcmFjdGVyKHRpc3NAaWRlbnQpLCBhcy5jaGFyYWN0ZXIodGlzc0BtZXRhLmRhdGEkcGxhdGUuYmFyY29kZSkpCmBgYAoKCiMgU3Vic2V0IGFuZCBpdGVyYXRlCgpXZSBjYW4gcmVwZWF0IHRoZSBhYm92ZSBhbmFseXNpcyBvbiBhIHN1YnNldCBvZiBjZWxscywgZGVmaW5lZCB1c2luZyBjbHVzdGVyIElEcyBvciBzb21lIG90aGVyIG1ldGFkYXRhLiBUaGlzIGlzIGEgZ29vZCB3YXkgdG8gZHJpbGwgZG93biBhbmQgZmluZCBzdWJzdHJ1Y3R1cmUuCgojIyBGaXJzdCBzdWJzZXQKCmBgYHtyfQojIFN1YnNldCBkYXRhIGJhc2VkIG9uIGNsdXN0ZXIgaWQKc3VidGlzcyA8LSBTdWJzZXREYXRhKG9iamVjdCA9IHRpc3MsIGlkZW50LnVzZSA9IGMoMCksIGRvLmNlbnRlciA9IEYsIGRvLnNjYWxlID0gRiwgY2VsbHMudXNlID0gKQoKIyBUbyBzdWJzZXQgZGF0YSBiYXNlZCBvbiBhbm5vdGF0aW9uIG9yIG90aGVyIG1ldGFkYXRhLCB5b3UgY2FuIGV4cGxpY2l0bHkgcGFzcyBjZWxsIG5hbWVzCgojIGFubm8gPSAndGh5bW9jeXRlJwojIGNlbGxzLnRvLnVzZSA9IHRpc3NAY2VsbC5uYW1lc1t3aGljaCh0aXNzQG1ldGEuZGF0YSRhbm5vdGF0aW9uID09IGFubm8pXQojIHN1YnRpc3MgPC0gU3Vic2V0RGF0YShvYmplY3QgPSB0aXNzLCBjZWxscy51c2UgPSBjZWxscy50by51c2UsIGRvLmNlbnRlciA9IEYsIGRvLnNjYWxlID0gRikKCmBgYAoKYGBge3J9CnN1YnRpc3MgPC0gTm9ybWFsaXplRGF0YShvYmplY3QgPSBzdWJ0aXNzKQpzdWJ0aXNzIDwtIFNjYWxlRGF0YShvYmplY3QgPSBzdWJ0aXNzLCB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJuUmVhZHMiLCAicGVyY2VudC5yaWJvIiwiUm40NXMiKSkKYGBgCgpgYGB7cn0Kc3VidGlzcyA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBzdWJ0aXNzLCBkby5wbG90ID0gVFJVRSwgeC5oaWdoLmN1dG9mZiA9IEluZiwgeS5jdXRvZmYgPSAwLjgpCnN1YnRpc3MgPC0gUnVuUENBKG9iamVjdCA9IHN1YnRpc3MsIHBjcy5jb21wdXRlID0gMjApCnN1YnRpc3MgPC0gUHJvamVjdFBDQShvYmplY3QgPSBzdWJ0aXNzLCBkby5wcmludCA9IEZBTFNFKQpgYGAKCgpSdW4gUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcy4KYGBge3J9CnN1YnRpc3MgPC0gUnVuUENBKG9iamVjdCA9IHN1YnRpc3MsIGRvLnByaW50ID0gRkFMU0UpCnN1YnRpc3MgPC0gUHJvamVjdFBDQShvYmplY3QgPSBzdWJ0aXNzLCBkby5wcmludCA9IEZBTFNFKQpgYGAKCmBgYHtyfQojIElmIHRoaXMgZmFpbHMgZm9yIHlvdXIgc3Vic2V0LCBpdCBtYXkgYmUgdGhhdCBjZWxscy51c2UgaXMgbW9yZSBjZWxscyB0aGFuIHlvdSBoYXZlIGxlZnQhIFRyeSByZWR1Y2luZyBpdC4KUENIZWF0bWFwKG9iamVjdCA9IHN1YnRpc3MsIHBjLnVzZSA9IDE6MywgY2VsbHMudXNlID0gMjAwLCBkby5iYWxhbmNlZCA9IFRSVUUsIGxhYmVsLmNvbHVtbnMgPSBGQUxTRSwgbnVtLmdlbmVzID0gMTIpCmBgYAoKTGF0ZXIgb24gKGluIEZpbmRDbHVzdGVycyBhbmQgVFNORSkgeW91IHdpbGwgcGljayBhIG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cyB0byB1c2UuIFRoaXMgaGFzIHRoZSBlZmZlY3Qgb2Yga2VlcGluZyB0aGUgbWFqb3IgZGlyZWN0aW9ucyBvZiB2YXJpYXRpb24gaW4gdGhlIGRhdGEgYW5kLCBpZGVhbGx5LCBzdXByZXNzaW5nIG5vaXNlLiBUaGVyZSBpcyBubyBjb3JyZWN0IGFuc3dlciB0byB0aGUgbnVtYmVyIHRvIHVzZSwgYnV0IGEgZGVjZW50IHJ1bGUgb2YgdGh1bWIgaXMgdG8gZ28gdW50aWwgdGhlIHBsb3QgcGxhdGVhdXMuCgpgYGB7cn0KUENFbGJvd1Bsb3Qob2JqZWN0ID0gc3VidGlzcykKYGBgCgpDaG9vc2UgdGhlIG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cyB0byB1c2UuCmBgYHtyfQojIFNldCBudW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHMuIApzdWIubi5wY3MgPSA2CmBgYAoKClRoZSBjbHVzdGVyaW5nIGlzIHBlcmZvcm1lZCBiYXNlZCBvbiBhIG5lYXJlc3QgbmVpZ2hib3JzIGdyYXBoLiBDZWxscyB0aGF0IGhhdmUgc2ltaWxhciBleHByZXNzaW9uIHdpbGwgYmUgam9pbmVkIHRvZ2V0aGVyLiBUaGUgTG91dmFpbiBhbGdvcml0aG0gbG9va3MgZm9yIGdyb3VwcyBvZiBjZWxscyB3aXRoIGhpZ2ggbW9kdWxhcml0eS0tbW9yZSBjb25uZWN0aW9ucyB3aXRoaW4gdGhlIGdyb3VwIHRoYW4gYmV0d2VlbiBncm91cHMuIFRoZSByZXNvbHV0aW9uIHBhcmFtZXRlciBkZXRlcm1pbmVzIHRoZSBzY2FsZS4uLmhpZ2hlciByZXNvbHV0aW9uIHdpbGwgZ2l2ZSBtb3JlIGNsdXN0ZXJzLCBsb3dlciByZXNvbHV0aW9uIHdpbGwgZ2l2ZSBmZXdlci4KCmBgYHtyfQojIFNldCByZXNvbHV0aW9uIApzdWIucmVzLnVzZWQgPC0gMQoKc3VidGlzcyA8LSBGaW5kQ2x1c3RlcnMob2JqZWN0ID0gc3VidGlzcywgcmVkdWN0aW9uLnR5cGUgPSAicGNhIiwgZGltcy51c2UgPSAxOnN1Yi5uLnBjcywgCiAgICByZXNvbHV0aW9uID0gc3ViLnJlcy51c2VkLCBwcmludC5vdXRwdXQgPSAwLCBzYXZlLlNOTiA9IFRSVUUpCmBgYAoKVG8gdmlzdWFsaXplIApgYGB7cn0KIyBJZiBjZWxscyBhcmUgdG9vIHNwcmVhZCBvdXQsIHlvdSBjYW4gcmFpc2UgdGhlIHBlcnBsZXhpdHkuIElmIHlvdSBoYXZlIGZldyBjZWxscywgdHJ5IGEgbG93ZXIgcGVycGxleGl0eSAoYnV0IG5ldmVyIGxlc3MgdGhhbiAxMCkuCnN1YnRpc3MgPC0gUnVuVFNORShvYmplY3QgPSBzdWJ0aXNzLCBkaW1zLnVzZSA9IDE6c3ViLm4ucGNzLCBzZWVkLnVzZSA9IDEwLCBwZXJwbGV4aXR5PTIwKQpgYGAKCmBgYHtyfQojIG5vdGUgdGhhdCB5b3UgY2FuIHNldCBkby5sYWJlbD1UIHRvIGhlbHAgbGFiZWwgaW5kaXZpZHVhbCBjbHVzdGVycwpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzLCBkby5sYWJlbCA9IFQpCmBgYAoKYGBge3J9CnN1YnRpc3MubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzLCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCB0aHJlc2gudXNlID0gMC4yNSkKYGBgCgpgYGB7cn0Kc3VidGlzcy5tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24oNiwgYXZnX2RpZmYpCmBgYAoKQ2hlY2sgZXhwcmVzc2lvbiBvZiBnZW5lcyBvZiBpbnRlcnNldC4KYGBge3J9CmdlbmVzX3RvX2NoZWNrID0gYygnQ2Q0JywnQ2Q4YScsJ0NkNTMnLCdDZDQ0JywnQ2Q3JywnQ2QyJywnSWwycmEnLCdSYWcxJywnWmFwNzAnLCdEbnR0JywnSWw3cicsJ0NkNjknLCdQZGNkMScsJ1NoaXNhNScsJ0NkNScsJ0xlZjEnLCdDY3I3JywnUHRjcmEnLCdJdG0yYScsJ0NkMjgnLCdDZDNlJykKCkZlYXR1cmVQbG90KHN1YnRpc3MsIGdlbmVzX3RvX2NoZWNrLCBwdC5zaXplID0gMSkKYGBgCgpEb3RwbG90cyBsZXQgeW91IHNlZSB0aGUgaW50ZW5zaXR5IG9mIGV4cHByZXNzaW9uIGFuZCB0aGUgZnJhY3Rpb24gb2YgY2VsbHMgZXhwcmVzc2luZyBmb3IgZWFjaCBvZiB5b3VyIGdlbmVzIG9mIGludGVyZXN0LgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTIwfQojIFRvIGNoYW5nZSB0aGUgeS1heGlzIHRvIHNob3cgcmF3IGNvdW50cywgYWRkIHVzZS5yYXcgPSBULgpEb3RQbG90KHN1YnRpc3MsIGdlbmVzX3RvX2NoZWNrLCBwbG90LmxlZ2VuZCA9IFQpCmBgYAoKSG93IGJpZyBhcmUgdGhlIGNsdXN0ZXJzPwpgYGB7cn0KdGFibGUoc3VidGlzc0BpZGVudCkKYGBgCgojIyBDaGVja2luZyBmb3IgYmF0Y2ggZWZmZWN0cwoKQ29sb3IgYnkgbWV0YWRhdGEsIGxpa2UgcGxhdGUgYmFyY29kZSwgdG8gY2hlY2sgZm9yIGJhdGNoIGVmZmVjdHMuCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJwbGF0ZS5iYXJjb2RlIikKYGBgCgpQcmludCBhIHRhYmxlIHNob3dpbmcgdGhlIGNvdW50IG9mIGNlbGxzIGluIGVhY2ggaWRlbnRpdHkgY2F0ZWdvcnkgZnJvbSBlYWNoIHBsYXRlLgoKYGBge3J9CnRhYmxlKGFzLmNoYXJhY3RlcihzdWJ0aXNzQGlkZW50KSwgYXMuY2hhcmFjdGVyKHN1YnRpc3NAbWV0YS5kYXRhJHBsYXRlLmJhcmNvZGUpKQpgYGAKCgoKIyMjIEFzc2lnbmluZyBzdWJhbm5vdGF0aW9ucwoKRm9yIHRoZSBzdWJzZXRzLCB3ZSBwcm9kdWNlIHN1YmFubm90YXRpb25zLiBUaGVzZSB3aWxsIGJlIHdyaXR0ZW4gYmFjayBhcyBtZXRhZGF0YSBpbiB0aGUgb3JpZ2luYWwgb2JqZWN0LCBzbyB3ZSBjYW4gc2VlIGFsbCBzdWJhbm5vdGF0aW9ucyB0b2dldGhlci4KCklmIHNvbWUgb2YgdGhlIGNsdXN0ZXJzIHlvdSBmaW5kIGluIHRoZSBzdWJzZXQgZGVzZXJ2ZSBhZGRpdGlvbmFsIGFubm90YXRpb24sIHlvdSBjYW4gYWRkIHRoYXQgcmlnaHQgaGVyZS4gVXNlIE5BIGZvciBjbHVzdGVycyBmb3Igd2hpY2ggbm8gc3ViYW5ub3RhdGlvbiBpcyBuZWVkZWQuCgpgYGB7cn0Kc3ViY2x1c3Rlci5pZHMgPC0gYygwLCAxLCAyLDMsNCw1KQpzdWJhbm5vdGF0aW9uIDwtIGMoImltbWF0dXJlX1NQX0NENCIsImltbWF0dXJlX1NQX0NENCIsIkRONCIsImltbWF0dXJlX1NQX0NENCIsIkltbWF0dXJlX1NQX0NEOCIsIkRQIikKCnN1YnRpc3NAbWV0YS5kYXRhWywnc3ViYW5ub3RhdGlvbiddIDwtIHBseXI6Om1hcHZhbHVlcyh4ID0gc3VidGlzc0BpZGVudCwgZnJvbSA9IHN1YmNsdXN0ZXIuaWRzLCB0byA9IHN1YmFubm90YXRpb24pCgp0aXNzQG1ldGEuZGF0YVtzdWJ0aXNzQGNlbGwubmFtZXMsJ3N1YmFubm90YXRpb24nXSA8LSBhcy5jaGFyYWN0ZXIoc3VidGlzc0BtZXRhLmRhdGEkc3ViYW5ub3RhdGlvbikKClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3MsIGRvLmxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuNSwgZ3JvdXAuYnk9J3N1YmFubm90YXRpb24nKQpgYGAKCgoKIyBTYXZlIHRoZSBSb2JqZWN0IGZvciBsYXRlcgpXaGVuIHlvdSBzYXZlIHRoZSBhbm5vdGF0ZWQgdGlzc3VlLCBwbGVhc2UgZ2l2ZSBpdCBhIG5hbWUuCgpgYGB7cn0KZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICd0aXNzdWVfc2V1cmF0X3JvYmonLCAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHRpc3N1ZV9vZl9pbnRlcmVzdCwgIl9zZXVyYXRfdGlzcy5Sb2JqIikpCnByaW50KGZpbGVuYW1lKQpzYXZlKHRpc3MsIGZpbGU9ZmlsZW5hbWUpCmBgYAoKYGBge3J9CiMgVG8gcmVsb2FkIGEgc2F2ZWQgb2JqZWN0CiMgZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICd0aXNzdWVfc2V1cmF0X3JvYmonLCAKIyAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAodGlzc3VlX29mX2ludGVyZXN0LCAiX3NldXJhdF90aXNzLlJvYmoiKSkKIyBsb2FkKGZpbGU9ZmlsZW5hbWUpCmBgYAoKCgojIEV4cG9ydCB0aGUgZmluYWwgbWV0YWRhdGEKClNvIHRoYXQgQmlvaHViIGNhbiBlYXNpbHkgY29tYmluZSBhbGwgeW91ciBhbm5vdGF0aW9ucywgcGxlYXNlIGV4cG9ydCB0aGVtIGFzIGEgc2ltcGxlIGNzdi4KCmBgYHtyfQpoZWFkKHRpc3NAbWV0YS5kYXRhKQpgYGAKCgpgYGB7cn0KZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICd0aXNzdWVfYW5ub3RhdGlvbl9jc3YnLCAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHRpc3N1ZV9vZl9pbnRlcmVzdCwgIl9hbm5vdGF0aW9uLmNzdiIpKQp3cml0ZS5jc3YodGlzc0BtZXRhLmRhdGFbLGMoJ3BsYXRlLmJhcmNvZGUnLCdhbm5vdGF0aW9uJywnY2VsbF9vbnRvbG9neV9pZCcpXSwgZmlsZT1maWxlbmFtZSkKYGBgCgoK